package com.qing.study.aop;

import ch.qos.logback.classic.LoggerContext;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;

@Aspect
@Component
public class LogAspect {

    private static final LoggerContext context = (LoggerContext) LoggerFactory.getILoggerFactory();
    private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);

    @Pointcut("execution(* com.qing.study.controller.*.*(..))")
    public void pointcut() {
    }

    @Around("pointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        // 获取请求信息
        ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert attributes != null;
        HttpServletRequest request = attributes.getRequest();
        String ip = request.getRemoteAddr();
        String method = request.getMethod();
        String url = request.getRequestURL().toString();

        // 记录日志信息
        String logInfo = String.format("IP : %s , 时间 : %s , 请求方式 : %s , URL : %s ", ip, new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()), method, url);
        String param = "";
        // 判断请求方式是GET还是POST
        if ("GET".equals(method)) {
            Enumeration<String> parameterNames = request.getParameterNames();
            StringBuilder sb = new StringBuilder();
            while (parameterNames.hasMoreElements()) {
                String paramName = parameterNames.nextElement();
                sb.append(paramName).append('=').append(request.getParameter(paramName)).append('&');
            }
            param += ", 参数： " + sb;  // 记录参数信息
        } else if ("POST".equals(method)) {
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(request.getInputStream()))) {
                StringBuilder sb = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    sb.append(line);
                }
                param += ", 请求体： " + sb;  // 记录请求体数据
            } catch (IOException e) {
                param += ", 请求体： 无";  // 如果没有请求体，记录这个信息
            }
        }

        // 执行方法并返回结果
        Object result = joinPoint.proceed();

        // 记录响应信息
        String responseInfo = String.format(" 响应结果 : %s , 响应码 : %d", result, getStatusCode(result));
        // System.out.println(responseInfo);
        logger.info("【" + logInfo + param + "," + responseInfo + "】");

        return result;
    }

    private int getStatusCode(Object result) {
        if (result instanceof ResponseEntity) {
            ResponseEntity<?> responseEntity = (ResponseEntity<?>) result;
            return responseEntity.getStatusCodeValue();
        } else {
            return 200;
        }
    }
}
